/*
  AVL Trees
  (C) 2006  Haibo Hu <hhb_3974@sohu.com>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  linux/lib/rbtree.c
*/

#include <rbtree.h>

#define AVL_LEFT 0
#define AVL_RIGHT 1


static inline int __height(struct rb_node *node)
{
	return node ?node->level :0;
}

static inline int __max_level(struct rb_node *p1, struct rb_node *p2)
{
	return (__height(p1) <= __height(p2)) ?__height(p2) :__height(p1);
}

static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *right = node->rb_right;

	if ((node->rb_right = right->rb_left))
		right->rb_left->rb_parent = node;
	right->rb_left = node;

	if ((right->rb_parent = node->rb_parent))
	{
		if (node == node->rb_parent->rb_left)
			node->rb_parent->rb_left = right;
		else
			node->rb_parent->rb_right = right;
	}
	else
		root->rb_node = right;
	node->rb_parent = right;
	node->level--;
}

static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *left = node->rb_left;

	if ((node->rb_left = left->rb_right))
		left->rb_right->rb_parent = node;
	left->rb_right = node;

	if ((left->rb_parent = node->rb_parent))
	{
		if (node == node->rb_parent->rb_right)
			node->rb_parent->rb_right = left;
		else
			node->rb_parent->rb_left = left;
	}
	else
		root->rb_node = left;
	node->rb_parent = left;
	node->level--;
}

static void __rb_rotate_left_right(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *left = node->rb_left;
	struct rb_node *right = left->rb_right;
	
	if ((node->rb_left = right->rb_right))
		right->rb_right->rb_parent = node;
	if ((left->rb_right = right->rb_left))
		right->rb_left->rb_parent = left;
	right->rb_left = left;
	left->rb_parent = right;
	
	if ((right->rb_parent = node->rb_parent))
	{
		if (node == node->rb_parent->rb_right)
			node->rb_parent->rb_right = right;
		else
			node->rb_parent->rb_left = right;
	}
	else
		root->rb_node = right;
	
	right->rb_right = node;
	node->rb_parent = right;
	node->level--;
	left->level--;
	right->level++;
}
	
static void __rb_rotate_right_left(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *right = node->rb_right;
	struct rb_node *left = right->rb_left;
	
	if ((node->rb_right = left->rb_left))
		left->rb_left->rb_parent = node;
	if ((right->rb_left = left->rb_right))
		left->rb_right->rb_parent = right;
	left->rb_right = right;
	right->rb_parent = left;
	
	if ((left->rb_parent = node->rb_parent))
	{
		if (node == node->rb_parent->rb_left)
			node->rb_parent->rb_left = left;
		else
			node->rb_parent->rb_right = left;
	}
	else
		root->rb_node = left;
	
	left->rb_left = node;
	node->rb_parent = left;
	node->level--;
	right->level--;
	left->level++;
}


void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *parent, *gparent;
	int i, level;
	
	if ((parent = node->rb_parent))
	{	if (node == parent->rb_left)
			i = AVL_LEFT;
		else
			i = AVL_RIGHT;
	}
	else
		return;

	while(1)
	{	
		level = parent->level;
		if (i == AVL_LEFT)
			parent->level = __max_level(node, parent->rb_right)+1;
		else
			parent->level = __max_level(node, parent->rb_left)+1;
		if(parent->level == level)
			break;
		if (!(gparent = parent->rb_parent))
			break;
			
		if(parent == gparent->rb_left)
		{	
			if ((__height(parent) - __height(gparent->rb_right)) == 3)
			{	if (i== AVL_LEFT)
					__rb_rotate_right(gparent, root);
				else
					__rb_rotate_left_right(gparent, root);
				break;
			}
			i = AVL_LEFT;
		}
		else
		{	
			if ((__height(parent) - __height(gparent->rb_left)) == 3)
			{	if (i== AVL_RIGHT)
					__rb_rotate_left(gparent, root);
				else
					__rb_rotate_right_left(gparent, root);
				break;
			}
			i = AVL_RIGHT;
		}
		
		node = parent;
		parent = gparent;
	}
}



void rb_erase(struct rb_node *node, struct rb_root *root)
{
	struct rb_node *child, *parent;
	int level;

	if (!node->rb_left)
		child = node->rb_right;
	else if (!node->rb_right)
		child = node->rb_left;
	else
	{
		struct rb_node *old = node, *left;

		node = node->rb_right;
		while ((left = node->rb_left))
			node = left;
		child = node->rb_right;
		parent = node->rb_parent;

		if (child)
			child->rb_parent = parent;
		if (parent)
		{
			if (parent->rb_left == node)
				parent->rb_left = child;
			else
				parent->rb_right = child;
		}
		else
			root->rb_node = child;

		if (node->rb_parent == old)
			parent = node;
		node->rb_parent = old->rb_parent;
		node->level = old->level;
		node->rb_right = old->rb_right;
		node->rb_left = old->rb_left;

		if (old->rb_parent)
		{
			if (old->rb_parent->rb_left == old)
				old->rb_parent->rb_left = node;
			else
				old->rb_parent->rb_right = node;
		} else
			root->rb_node = node;

		old->rb_left->rb_parent = node;
		if (old->rb_right)
			old->rb_right->rb_parent = node;
		goto rebalance;
	}

	parent = node->rb_parent;

	if (child)
		child->rb_parent = parent;
	if (parent)
	{
		if (parent->rb_left == node)
			parent->rb_left = child;
		else
			parent->rb_right = child;
	}
	else
		root->rb_node = child;

rebalance:
	while (parent)
	{	if (child == parent->rb_left)
		{	struct rb_node *right = parent->rb_right;
			level = parent->level;
			parent->level = __max_level(child, right)+1;
			if(parent->level == level)
				break;
			
			if ((__height(right) - __height(child)) == 3)
			{
				if (__height(right->rb_left) == __height(right->rb_right))
				{	right->level++;
					__rb_rotate_left(parent, root);
					break;
				}
				if (__height(right->rb_left) < __height(right->rb_right))
				{	parent->level--;
					__rb_rotate_left(parent, root);
					child = right;
					parent = child->rb_parent;
				}
				else
				{	parent->level--;
					__rb_rotate_right_left(parent, root);
					child = right->rb_parent;
					parent = child->rb_parent;
				}
			}
			else
			{	child = parent;
				parent = child->rb_parent;
			}
		}
		else
		{
			struct rb_node *left = parent->rb_left;
			level = parent->level;
			parent->level = __max_level(child, left)+1;
			if(parent->level == level)
				break;
			
			if ((__height(left) - __height(child)) == 3)
			{
				if (__height(left->rb_right) == __height(left->rb_left))
				{	left->level++;
					__rb_rotate_right(parent, root);
					break;
				}
				if (__height(left->rb_right) < __height(left->rb_left))
				{	parent->level--;
					__rb_rotate_right(parent, root);
					child = left;
					parent = child->rb_parent;
				}
				else
				{	parent->level--;
					__rb_rotate_left_right(parent, root);
					child = left->rb_parent;
					parent = child->rb_parent;
				}
			}
			else
			{	child = parent;
				parent = child->rb_parent;
			}
		}
	}
}

/*
 * This function returns the first node (in sort order) of the tree.
 */
struct rb_node *rb_first(struct rb_root *root)
{
	struct rb_node	*n;

	n = root->rb_node;
	if (!n)
		return 0;
	while (n->rb_left)
		n = n->rb_left;
	return n;
}

struct rb_node *rb_next(struct rb_node *node)
{
	/* If we have a right-hand child, go down and then left as far
	   as we can. */
	if (node->rb_right) {
		node = node->rb_right; 
		while (node->rb_left)
			node=node->rb_left;
		return node;
	}

	/* No right-hand children.  Everything down and left is
	   smaller than us, so any 'next' node must be in the general
	   direction of our parent. Go up the tree; any time the
	   ancestor is a right-hand child of its parent, keep going
	   up. First time it's a left-hand child of its parent, said
	   parent is our 'next' node. */
	while (node->rb_parent && node == node->rb_parent->rb_right)
		node = node->rb_parent;

	return node->rb_parent;
}

struct rb_node *rb_prev(struct rb_node *node)
{
	/* If we have a left-hand child, go down and then right as far
	   as we can. */
	if (node->rb_left) {
		node = node->rb_left; 
		while (node->rb_right)
			node=node->rb_right;
		return node;
	}

	/* No left-hand children. Go up till we find an ancestor which
	   is a right-hand child of its parent */
	while (node->rb_parent && node == node->rb_parent->rb_left)
		node = node->rb_parent;

	return node->rb_parent;
}

void rb_replace_node(struct rb_node *victim, struct rb_node *new,
		     struct rb_root *root)
{
	struct rb_node *parent = victim->rb_parent;

	/* Set the surrounding nodes to point to the replacement */
	if (parent) {
		if (victim == parent->rb_left)
			parent->rb_left = new;
		else
			parent->rb_right = new;
	} else {
		root->rb_node = new;
	}
	if (victim->rb_left)
		victim->rb_left->rb_parent = new;
	if (victim->rb_right)
		victim->rb_right->rb_parent = new;

	/* Copy the pointers/colour from the victim to the replacement */
	*new = *victim;
}
